package com.cg.bank.util;

import com.mchange.v2.c3p0.ComboPooledDataSource;

import javax.sql.CommonDataSource;
import javax.sql.DataSource;
import java.sql.Connection;
import java.sql.SQLException;

public class JdbcUtils {
    // 存储连接池(数据源)
//    private static ComboPooledDataSource dataSource = new ComboPooledDataSource();

    private static ComboPooledDataSource dataSource;
    // 事务专用连接(事务之间必须使用同一个连接)
    private static ThreadLocal<Connection> transactionThread = new ThreadLocal<>();

    public static void setDataSource(CommonDataSource source) {
        dataSource = (ComboPooledDataSource) source;
    }

    /**
     * 获得连接池中连接
     *
     * @return connection
     * @throws SQLException
     */
    public static Connection getConnection() throws SQLException {
        //printPoolInfos();
        // 当事务连接不为空表示已开启了事务连接,否则返回正常连接
        Connection connection = transactionThread.get();
        if (connection != null) return connection;
        return dataSource.getConnection();
    }

    /**
     * 打印连接信息
     *
     * @throws SQLException
     */
    @SuppressWarnings("unused")
	private static void printPoolInfos() throws SQLException {
        System.out.println("当前连接数:" + dataSource.getNumBusyConnections());
        System.out.println("空闲连接数：" + dataSource.getNumIdleConnections());
        System.out.println("总连接数:" + dataSource.getNumConnections());
    }

    /**
     * 开始事务
     * 此操作将获得一个事务专用连接
     *
     * @throws SQLException 在同一方法中多次调用该方法将抛出SQLException
     */
    public static void beginTransaction() throws SQLException {
        // 从当前线程获取连接
        Connection connection = transactionThread.get();
        if (connection != null) throw new SQLException("transaction had begined");
        // 获取一个连接并作为事务专用连接
        connection = getConnection();
        // 开启事务
        connection.setAutoCommit(false);
        // 为当前线程保留连接
        transactionThread.set(connection);
    }

    /**
     * 提交事务
     * 此操作默认将关闭事务专用连接
     *
     * @throws SQLException
     */
    public static void commitTransaction() throws SQLException {
        Connection connection = transactionThread.get();
        if (connection == null) throw new SQLException("not begin transaction");
        // 提交事务
        connection.commit();
        // 关闭事务专用连接
        connection.close();
        // 表示事务连接已结束
        // 关闭连接后并不会将连接设置为null，保证其他操作可以获得正常连接,防止其他连接获取已关闭的事务连接异常
        transactionThread.remove();// 从当前线程中移除连接
    }

    /**
     * 回滚事务
     * 此操作默认将关闭事务专用连接
     *
     * @throws SQLException
     */
    public static void rollbackTransaction() throws SQLException {
        Connection connection = transactionThread.get();
        if (connection == null) throw new SQLException("not begin transaction");
        // 回滚事务
        connection.rollback();
        connection.close();
        transactionThread.remove();
    }

    /**
     * 释放连接
     *
     * @param connection 需要关闭的连接(主要处理费事务连接)
     * @throws SQLException
     */
    public static void releaseConnection(Connection connection) throws SQLException {
        Connection con = transactionThread.get();
        // 如果事务连接已关闭，则该连接为普通连接需要关闭
        if (con == null) connection.close();
        // 参数连接是否与事务相等,否则需要关闭
        if (con != connection) connection.close();
    }

    /**
     * 获取连接池
     *
     * @return connection pool 连接池对象
     */
    public static DataSource getDataSource() {
        return dataSource;
    }

}
